﻿using System;
using System.Web;
using System.IO;
using SystemX.Infrastructure;
using SystemX.Utility;

namespace SystemX.Web
{
    public static partial class Utils
    {
        private static string _RelativeWebRoot;
        /// <summary>
        /// Gets the relative root of the website.
        /// </summary>
        /// <value>A string that ends with a '/'.</value>
        public static string RelativeWebRoot
        {
            get
            {
				if (_RelativeWebRoot == null)
				{
					var virtualPath=AppSettingsHelper.Instance.GetString("App.VirtualPath","~/");
					_RelativeWebRoot = VirtualPathUtility.ToAbsolute(virtualPath);
				}

                return _RelativeWebRoot;
            }
        }

        //private static Uri _AbsoluteWebRoot;

        /// <summary>
        /// Gets the absolute root of the website.
        /// </summary>
        /// <value>A string that ends with a '/'.</value>
        public static Uri AbsoluteWebRoot
        {
            get
            {
                HttpContext context = HttpContext.Current;
                if (context == null)
                    throw new System.Net.WebException("The current HttpContext is null");

                if (context.Items["absoluteurl"] == null)
                    context.Items["absoluteurl"] = new Uri(context.Request.Url.GetLeftPart(UriPartial.Authority) + RelativeWebRoot);

                return context.Items["absoluteurl"] as Uri;
            }
        }

        /// <summary>
        /// Converts a relative URL to an absolute one.
        /// </summary>
        public static Uri ConvertToAbsolute(Uri relativeUri)
        {
            return ConvertToAbsolute(relativeUri.ToString());
        }

        /// <summary>
        /// Converts a relative URL to an absolute one.
        /// </summary>
        /// <param name="relativeUri">"/wwwRoot/xx/yy.aspx" or "~/xx/yy.aspx" or "wwwRoot/xx/yy.aspx"</param>
        public static Uri ConvertToAbsolute(string relativeUri)
        {
            if (string.IsNullOrEmpty(relativeUri))
                throw new ArgumentNullException("relativeUri");

            string absolute = AbsoluteWebRoot.ToString();
            int index = absolute.LastIndexOf(RelativeWebRoot.ToString());

            if (relativeUri.StartsWith("~"))
            {//app relative url.
                relativeUri = absolute.Substring(index) + relativeUri.Substring(2);
            }
            if (!relativeUri.StartsWith("/"))
            {
				relativeUri = String.Format("/{0}", relativeUri);
            }

            var tempUrl = absolute.Substring(0, index) + relativeUri;
            return new Uri(tempUrl);
        }
        /// <summary>
        /// Convert a absolute physical path to a relative url.
        /// </summary>
        /// <param name="absolutePhysicalPath"></param>
        /// <param name="appRelative">app relative url startswith "~"</param>
        /// <returns></returns>
        public static string ConvertPhysicalPathToRelative(string absolutePhysicalPath, bool appRelative)
        {
            if (!File.Exists(absolutePhysicalPath) && !Directory.Exists(absolutePhysicalPath)) return null;
            HttpContext context = HttpContext.Current;
            if (context == null)
                throw new System.Net.WebException("The current HttpContext is null");

            var tempPath = absolutePhysicalPath.Replace(context.Request.PhysicalApplicationPath, "");
            tempPath.Replace("\\", "/");
            if (tempPath.StartsWith("/"))
            {
                tempPath = tempPath.Substring(1);
            }
            if (!appRelative)
            {
                tempPath = RelativeWebRoot + tempPath;
            }
            else
            {
				tempPath = String.Format("~/{0}", tempPath);
            }
            return tempPath;
        }
        /// <summary>
        /// Convert a absolute url to a relative url
        /// </summary>
        /// <param name="absoluteUrl"></param>
        /// <param name="appRelative">app relative url startswith "~"</param>
        /// <returns></returns>
        public static string ConvertToRelative(string absoluteUrl, bool appRelative)
        {

            var tempPath = absoluteUrl.Replace(AbsoluteWebRoot.ToString(), "");
            if (tempPath.StartsWith("/"))
            {
                tempPath = tempPath.Substring(1);
            }
            if (!appRelative)
            {
                tempPath = RelativeWebRoot + tempPath;
            }
            else
            {
				tempPath = String.Format("~/{0}", tempPath);
            }
            return tempPath;
        }
        /// Retrieves the subdomain from the specified URL.
        /// </summary>
        /// <param name="url">The URL from which to retrieve the subdomain.</param>
        /// <returns>The subdomain if it exist, otherwise null.</returns>
        public static string GetSubDomain(Uri url)
        {
            if (url.HostNameType == UriHostNameType.Dns)
            {
                string host = url.Host;
                if (host.Split('.').Length > 2)
                {
                    int lastIndex = host.LastIndexOf(".");
                    int index = host.LastIndexOf(".", lastIndex - 1);
                    return host.Substring(0, index);
                }
            }

            return null;
        }
        /// <summary>
        /// Physical app root
        /// </summary>
        public static string PhysicalAppRoot {
            get
            {
                var retVal = string.Empty;
                if (Utils.AppIsRunOnWeb)
                {
                    retVal = HttpContext.Current.Server.MapPath("~/");
                }
                else { 
                    retVal=AppDomain.CurrentDomain.BaseDirectory;
                }
                if (!retVal.EndsWith(@"\")) {
                    retVal = string.Format(@"{0}\",retVal);
                };
                return retVal;
            }
        }
        /// <summary>
        /// Convert an app root relative path to a physical path
        /// </summary>
        /// <param name="relativeToAppRoot"></param>
        /// <returns></returns>
        public static string ConvertToPhysicalPath(string relativeToAppRoot) {
			return ConvertToPhysicalPath(relativeToAppRoot, false);
        }
		/// <summary>
		/// Convert an app root relative path to a physical path
		/// </summary>
		/// <param name="relativeToAppRoot"></param>
		/// <returns></returns>
		public static string ConvertToPhysicalPath(string relativeToAppRoot,bool isFolder)
		{
			//In window OS,physical path would look like E:\XXX\YYYY
			if (relativeToAppRoot.IndexOf(@":\") == 1)
			{
				return relativeToAppRoot;
			};
			relativeToAppRoot = relativeToAppRoot.CHSToPinyin(true);
			relativeToAppRoot = relativeToAppRoot.RemoveIllegalPathChars();
			relativeToAppRoot = relativeToAppRoot.SlashToBackslash();
			if ((!relativeToAppRoot.EndsWith(@"\"))&&isFolder)
			{
				relativeToAppRoot = string.Format(@"{0}\", relativeToAppRoot);
			}
			if ((!isFolder) && relativeToAppRoot.EndsWith(@"\")) {
				relativeToAppRoot = relativeToAppRoot.Substring(0, relativeToAppRoot.Length - 1);
			}
			if (relativeToAppRoot.StartsWith(@"\"))
			{
				relativeToAppRoot = relativeToAppRoot.Substring(1);
			}
			while (relativeToAppRoot.IndexOf(@"\\") >= 0)
			{
				relativeToAppRoot = relativeToAppRoot.Replace(@"\\", @"\");
			}
			return string.Format("{0}{1}", PhysicalAppRoot, relativeToAppRoot);
		}
    }
}
